'''
Copyright (c) [2021] [Li Yizhou]
[Intellen - Network] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2. 
You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
See the Mulan PSL v2 for more details. 

File    : FileTrans.py
Author  : Aiden
Project : Intellen
Url     : https://gitee.com/intellen/network
'''
from Core import *
import platform
import ast, queue
import os

__version__ = '0.1.1'

def listdir(path):
    if os.path.exists(path) == True:
        dat = {"files":[],"folders":[],"unknows":[]}
        for i in os.listdir(path):
            if os.path.isdir(path + i) == True:
                dat["folders"].append(i)
            elif os.path.isfile(path + i) == True:
                dat["files"].append(i)
            else:
                dat["unknows"].append(i)
        return dat

class Command(threading.Thread):
    def __init__(self, tree):
        super().__init__()
        self.tree = tree
    
    def file(self, data):
        todo = data['_cmd']
        del data['_cmd']
        cmd = todo.get("cmd", "list")
        if cmd == "list":
            path = todo.get("path")
            try:
                result = listdir(path)
            except:
                result = {"rs":"PathError"}
            data["_result"] = result
            self.tree.send(str(data).encode('utf-8'))
            
    def run(self):
        while True:
            data = self.tree.cmds.get()
            self.tree.cmds.task_done()
            data = ast.literal_eval(data)
            todo = data['_cmd']
            if type(todo) == str:
                result = os.popen(todo)
                result = result.read()
                req = data
                req['_result'] = result
                req['_recver'] = req['_from']
                del req['_from']
                del req['_cmd']
                self.tree.send(str(req).encode('utf-8'))
            elif type(todo) == dict:
                data['_recver'] = data['_from']
                del data['_from']
                self.file(data)

class GetData_File(Orgin):
    def run(self):
        self.cmds = queue.Queue()
        self.cmd = Command(self)
        self.cmd.start()
        while True:
            try:
                data = self.recv()
                if '_cmd' in data:
                    self.cmds.put(data)
                    continue
                if '_sys' in data:
                    self.spe.put(data)
                    continue
                self.que.put(data)
            except:
                break

class Transfer(CoreTree):
    def __init__(self, host, port=1305):
        super().__init__(host, port=1305)
        self.add['file'] = True
        self.add['system'] = platform.platform()
    
    def active(self):
        if not self.act:return False
        self.input = InputData(self.conn)
        self.get = GetData_File(self.conn)
        self.input.start()
        self.get.start()
        return True
    
    def check(self, dev):
        LineCode = RanCode(3)
        self.send({'_cmd':'alive', '_sys':LineCode})
        while True:
            try:result = ast.literal_eval(self.get.spe.get(timeout=5))
            except:
                result = {}
                break
            if result.get('_sys') == LineCode:
                self.get.spe.task_done()
                break
        target = result.get(dev, {'file':False})
        if target['file'] == False:return False,
        return True
    
    def cmd(self, target, cmd):
        able = self.check(target)
        if not able:return False
        LineCode = RanCode(3)
        req = {
            '_cmd':cmd,
            '_sys':LineCode,
        }
        self.send(req, target)
        while True:
            try:result = ast.literal_eval(self.get.spe.get(timeout=5))
            except:
                result = {}
                break
            if result.get('_sys') == LineCode:
                self.get.spe.task_done()
                break
        return result.get('_result', '404')
    
    def file(self, mode, target, path):
        able = self.check(target)
        if not able:return False
        LineCode = RanCode(3)
        if mode == "list":
            req = {
                '_cmd':{"cmd":"list", "path":path},
                '_sys':LineCode,
            }
        else:return False
        self.send(req, target)
        while True:
            try:result = ast.literal_eval(self.get.spe.get(timeout=5))
            except:
                result = {}
                break
            if result.get('_sys') == LineCode:
                self.get.spe.task_done()
                break
        if mode == "list":
            return result.get('_result', '404')